⚽ FIFA WORLD CUP 2026     NJ-LIS-LON

SWEEPSTAKE • 11 JUN – 19 JUL 2026
CAN MEX USA
€60 pot
Live — last synced 22:13 • 1 matches played • 2 team(s) updated
⚽ YOUR TEAMS PLAYING TODAY
MEX vs 🇿🇦 RSA 20:00 BST / 3:00pm ET • Mexico City
KOR vs CZE 03:00† BST / 10:00pm ET • Guadalajara
🔓Owner mode active

👤 Players

Add everyone taking part. You need at least 2 players to run the draw.

Suhani
Maya
Paarth_siuu
Aarav
Aryan
Radhi
Pooja
Nina
D K Kotecha
Jilane
Anit
CR7

🅾 Pin Top-12 Teams

Optionally assign one top-12 team to a specific player. Pinned teams are locked in before the draw runs — max one pin per player.

Suhani
Maya
Paarth_siuu
Aarav
Aryan
Radhi
Pooja
Nina
D K Kotecha
Jilane
Anit
CR7

💰 Pot (optional)

12 players × €5 = €60 total pot

📶 Live Results API

Enter your football-data.org API key to auto-sync results every time you refresh.

Connected ✔

🏆 All 48 Qualified Teams

Draw is seeded — every player gets 1 top-12 + 1 ranked 13–20. Official codes & flags shown.

FRA #1ESP #2ARG #3ENG #4POR #5BRA #6NED #7MAR #8BEL #9GER #10CRO #11COL #13SEN #14MEX #15USA #16URU #17JPN #18SUI #19KOR #22AUT #25🇦🇺 AUS #26ECU #28TUR #29ALG #30NOR #31SWE #33IRN #35SCO #36PAR #37CZE #38GHA #40EGY #41KSA #56PAN #57TUN #58CAN #59CIV #60NZL #63QAT #65BIH #66IRQ #68JOR #70COD #74🇿🇦 RSA #76HAI #83UZB #87CPV #90CUW #104

🎲 The Draw

Seeded draw — everyone gets at least 1 top-12 team and 1 ranked 13–20. Hit the button when everyone’s ready!

Draw complete — 12 players, all 48 teams assigned.

S
Suhani
0 pts
ESP
ESP
Spain
★ #2
SEN
SEN
Senegal
#14
SUI
SUI
Switzerland
#19
IRN
IRN
Iran
#35
M
Maya
1 pts
FRA
FRA
France
★ #1
🇿🇦
RSA
South Africa
#76
Group exit
EGY
EGY
Egypt
#41
URU
URU
Uruguay
#17
P
Paarth_siuu
0 pts
NED
NED
Netherlands
★ #7
🇦🇺
AUS
Australia
#26
KOR
KOR
South Korea
#22
QAT
QAT
Qatar
#65
A
Aarav
0 pts
POR
POR
Portugal
★ #5
ALG
ALG
Algeria
#30
BIH
BIH
Bosnia-Herz
#66
ECU
ECU
Ecuador
#28
A
Aryan
0 pts
BEL
BEL
Belgium
★ #9
GHA
GHA
Ghana
#40
TUR
TUR
Turkey
#29
CZE
CZE
Czechia
#38
R
Radhi
1 pts
ARG
ARG
Argentina
★ #3
MEX
MEX
Mexico
#15
Group exit
SWE
SWE
Sweden
#33
JPN
JPN
Japan
#18
P
Pooja
0 pts
ENG
ENG
England
★ #4
NZL
NZL
New Zealand
#63
CIV
CIV
Ivory Coast
#60
AUT
AUT
Austria
#25
N
Nina
0 pts
BRA
BRA
Brazil
★ #6
UZB
UZB
Uzbekistan
#87
PAN
PAN
Panama
#57
CPV
CPV
Cape Verde
#90
DK
D K Kotecha
0 pts
GER
GER
Germany
★ #10
JOR
JOR
Jordan
#70
HAI
HAI
Haiti
#83
NOR
NOR
Norway
#31
J
Jilane
0 pts
CRO
CRO
Croatia
#11
SCO
SCO
Scotland
#36
IRQ
IRQ
Iraq
#68
CUW
CUW
Curacao
#104
A
Anit
0 pts
MAR
MAR
Morocco
★ #8
KSA
KSA
Saudi Arabia
#56
TUN
TUN
Tunisia
#58
COD
COD
DR Congo
#74
C
CR7
0 pts
COL
COL
Colombia
#13
PAR
PAR
Paraguay
#37
USA
USA
USA
#16
CAN
CAN
Canada
#59
12
Players
€60
Total pot
46
Teams still in

🏆 Leaderboard

🥇
M
Maya
FRA FRA🇿🇦 RSA · Group exitEGY EGYURU URU
1pts
🥈
R
Radhi
ARG ARGMEX MEX · Group exitSWE SWEJPN JPN
1pts
🥉
S
Suhani
ESP ESPSEN SENSUI SUIIRN IRN
0pts
4
P
Paarth_siuu
NED NED🇦🇺 AUSKOR KORQAT QAT
0pts
5
A
Aarav
POR PORALG ALGBIH BIHECU ECU
0pts
6
A
Aryan
BEL BELGHA GHATUR TURCZE CZE
0pts
7
P
Pooja
ENG ENGNZL NZLCIV CIVAUT AUT
0pts
8
N
Nina
BRA BRAUZB UZBPAN PANCPV CPV
0pts
9
DK
D K Kotecha
GER GERJOR JORHAI HAINOR NOR
0pts
10
J
Jilane
CRO CROSCO SCOIRQ IRQCUW CUW
0pts
11
A
Anit
MAR MARKSA KSATUN TUNCOD COD
0pts
12
C
CR7
COL COLPAR PARUSA USACAN CAN
0pts
💰 PRIZE BREAKDOWN
🥇
Maya
1st place
€35
🥈
Radhi
2nd place
€15
🥉
Suhani
3rd place
€10

⛳ Update Results

If auto-sync is on, this updates automatically. You can also mark results manually.
Points: Group=1 • R32=2 • R16=4 • QF=6 • SF=9 • Runner-up=12 • Winner=20

FRA FRA France Maya
ESP ESP Spain Suhani
ARG ARG Argentina Radhi
ENG ENG England Pooja
POR POR Portugal Aarav
BRA BRA Brazil Nina
NED NED Netherlands Paarth_siuu
MAR MAR Morocco Anit
BEL BEL Belgium Aryan
GER GER Germany D K Kotecha
CRO CRO Croatia Jilane
COL COL Colombia CR7
SEN SEN Senegal Suhani
MEX MEX Mexico Radhi
USA USA USA CR7
URU URU Uruguay Maya
JPN JPN Japan Radhi
SUI SUI Switzerland Suhani
KOR KOR South Korea Paarth_siuu
AUT AUT Austria Pooja
🇦🇺 AUS Australia Paarth_siuu
ECU ECU Ecuador Aarav
TUR TUR Turkey Aryan
ALG ALG Algeria Aarav
NOR NOR Norway D K Kotecha
SWE SWE Sweden Radhi
IRN IRN Iran Suhani
SCO SCO Scotland Jilane
PAR PAR Paraguay CR7
CZE CZE Czechia Aryan
GHA GHA Ghana Aryan
EGY EGY Egypt Maya
KSA KSA Saudi Arabia Anit
PAN PAN Panama Nina
TUN TUN Tunisia Anit
CAN CAN Canada CR7
CIV CIV Ivory Coast Pooja
NZL NZL New Zealand Pooja
QAT QAT Qatar Paarth_siuu
BIH BIH Bosnia-Herz Aarav
IRQ IRQ Iraq Jilane
JOR JOR Jordan D K Kotecha
COD COD DR Congo Anit
🇿🇦 RSA South Africa Maya
HAI HAI Haiti D K Kotecha
UZB UZB Uzbekistan Nina
CPV CPV Cape Verde Nina
CUW CUW Curacao Jilane

📅 Match Schedule

All 104 matches • UK / BST times • 11 Jun – 19 Jul 2026 • = England or Scotland match

Thu 11 Jun Today
MEXMEX vs RSA🇿🇦
20:00 BST Mexico City Group A
KORKOR vs CZECZE
03:00† BST Guadalajara Group A
Fri 12 Jun Tomorrow
CANCAN vs BIHBIH
20:00 BST Toronto Group B
USAUSA vs PARPAR
02:00† BST Los Angeles Group D
Sat 13 Jun In 2 days
QATQAT vs SUISUI
20:00 BST San Francisco Group B
BRABRA vs MARMAR
23:00 BST New York/NJ Group C
HAIHAI vs SCOSCO
02:00† BST Boston Group C
🇦🇺AUS vs TURTUR
05:00† BST Vancouver Group D
Sun 14 Jun In 3 days
GERGER vs CUWCUW
19:00 BST Houston Group E
NEDNED vs JPNJPN
22:00 BST Dallas Group F
CIVCIV vs ECUECU
01:00† BST Philadelphia Group E
SWESWE vs TUNTUN
04:00† BST Monterrey Group F
Mon 15 Jun In 4 days
ESPESP vs CPVCPV
18:00 BST Atlanta Group H
BELBEL vs EGYEGY
21:00 BST Vancouver Group G
KSAKSA vs URUURU
00:00† BST Miami Group H
IRNIRN vs NZLNZL
05:00† BST Los Angeles Group G
Tue 16 Jun In 5 days
FRAFRA vs SENSEN
21:00 BST New York/NJ Group I
IRQIRQ vs NORNOR
00:00† BST Boston Group I
ARGARG vs ALGALG
03:00† BST Kansas City Group J
AUTAUT vs JORJOR
08:00† BST San Francisco Group J
Wed 17 Jun In 6 days
PORPOR vs CODCOD
19:00 BST Houston Group K
ENGENG vs CROCRO
22:00 BST Dallas Group L
GHAGHA vs PANPAN
01:00† BST Toronto Group L
UZBUZB vs COLCOL
04:00† BST Mexico City Group K
Thu 18 Jun In 7 days
CZECZE vs RSA🇿🇦
18:00 BST Atlanta Group A
SUISUI vs BIHBIH
21:00 BST Los Angeles Group B
CANCAN vs QATQAT
02:00† BST Vancouver Group B
MEXMEX vs KORKOR
04:00† BST Guadalajara Group A
Fri 19 Jun
🇿🇦RSA vs MARMAR
21:00 BST Boston Group C
USAUSA vs AUS🇦🇺
22:00 BST Seattle Group D
BRABRA vs HAIHAI
02:00† BST Philadelphia Group C
TURTUR vs PARPAR
04:00† BST San Francisco Group D
Sat 20 Jun
NEDNED vs SWESWE
19:00 BST Houston Group F
GERGER vs CIVCIV
22:00 BST Toronto Group E
ECUECU vs CUWCUW
02:00† BST Kansas City Group E
TUNTUN vs JPNJPN
06:00† BST Monterrey Group F
Sun 21 Jun
ESPESP vs KSAKSA
18:00 BST Atlanta Group H
BELBEL vs IRNIRN
21:00 BST Los Angeles Group G
URUURU vs CPVCPV
00:00† BST Miami Group H
NZLNZL vs EGYEGY
05:00† BST Vancouver Group G
Mon 22 Jun
ARGARG vs AUTAUT
19:00 BST Dallas Group J
FRAFRA vs IRQIRQ
23:00 BST Philadelphia Group I
NORNOR vs SENSEN
02:00† BST New York/NJ Group I
JORJOR vs ALGALG
07:00† BST San Francisco Group J
Tue 23 Jun
PORPOR vs UZBUZB
19:00 BST Houston Group K
ENGENG vs GHAGHA
22:00 BST Seattle Group L
CROCRO vs PANPAN
01:00† BST Toronto Group L
COLCOL vs CODCOD
05:00† BST Kansas City Group K
Wed 24 Jun
MEXMEX vs CZECZE
20:00 BST Mexico City Group A
KORKOR vs RSA🇿🇦
20:00 BST Guadalajara Group A
BIHBIH vs QATQAT
23:00 BST Toronto Group B
SUISUI vs CANCAN
23:00 BST Vancouver Group B
Thu 25 Jun
SCOSCO vs BRABRA
20:00 BST Philadelphia Group C
MARMAR vs HAIHAI
20:00 BST New York/NJ Group C
PARPAR vs AUS🇦🇺
23:00 BST Los Angeles Group D
TURTUR vs USAUSA
23:00 BST Seattle Group D
Fri 26 Jun
CUWCUW vs GERGER
20:00 BST Kansas City Group E
ECUECU vs CIVCIV
20:00 BST Philadelphia Group E
JPNJPN vs NEDNED
23:00 BST Dallas Group F
TUNTUN vs SWESWE
23:00 BST Monterrey Group F
Sat 27 Jun
EGYEGY vs BELBEL
20:00 BST Vancouver Group G
NZLNZL vs IRNIRN
20:00 BST Los Angeles Group G
CPVCPV vs ESPESP
23:00 BST Miami Group H
URUURU vs KSAKSA
23:00 BST Atlanta Group H
Sun 28 Jun
SENSEN vs FRAFRA
20:00 BST New York/NJ Group I
NORNOR vs IRQIRQ
20:00 BST Boston Group I
ALGALG vs ARGARG
23:00 BST Kansas City Group J
JORJOR vs AUTAUT
23:00 BST San Francisco Group J
Mon 29 Jun
CODCOD vs PORPOR
20:00 BST Houston Group K
COLCOL vs UZBUZB
20:00 BST Mexico City Group K
PANPAN vs ENGENG
23:00 BST Toronto Group L
GHAGHA vs CROCRO
23:00 BST Dallas Group L
Fri 3 Jul – Mon 7 Jul
Round of 32 (8 matches)
KNOCKOUT
Sat 5 Jul – Tue 8 Jul
Round of 16 (8 matches)
KNOCKOUT
Fri 10 Jul – Sun 12 Jul
Quarter-finals (4 matches)
KNOCKOUT
Wed 15 – Thu 16 Jul
Semi-finals
KNOCKOUT
Sun 18 Jul
3rd place play-off — Miami
23:00 BSTKNOCKOUT
Sun 19 Jul
🏆 FINAL — New York / New Jersey
20:00 BSTKNOCKOUT

💬 Share to WhatsApp

💾 Download

Save the app as a single HTML file. Share it with family — they open it in any browser.

🗣 Banter Board Live

Family chat — trash talk welcome. Messages are shared live across all devices.

1
111 Jun 12:47
test
1
111 Jun 12:31
hello
1
1211 Jun 12:02
hello
1
1210 Jun 23:35
hello
1
1210 Jun 18:27
13
1
1210 Jun 16:12
1-2-3
N
Nina10 Jun 14:48
testing
1
1210 Jun 14:46
hello
N
Nina10 Jun 14:44
test
TU
Test User10 Jun 12:54
Hello from console
TU
Test User10 Jun 12:48
Hello from console
TU
Test User10 Jun 12:48
Hello from console
1
110 Jun 12:36
test
1
110 Jun 12:36
test
1
110 Jun 12:35
test
1
110 Jun 12:32
hi
1
110 Jun 12:31
hi
1
110 Jun 12:31
hi
N
Nina10 Jun 12:09
test
N
Nina10 Jun 10:36
test
N
Nina10 Jun 10:16
test

🏆 Route to the Final

Predict the knockout bracket — in R32 use the dropdowns to pick which team from each group advances, then tap a team to pick the match winner. They advance automatically all the way to the final.

Uses the 12 official WC 2026 groups

',inject+''); var blob=new Blob([html],{type:'text/html'}); var a=document.createElement('a');a.href=URL.createObjectURL(blob);a.download='wc2026-sweepstake.html';a.click(); } /* -- BOOT -- */ /* -- TODAY'S MATCHES BAR -- */ /* -- TIME HELPERS -- */ function bstToET(bstStr){ // bstStr like "20:00" or "02:00" (dagger already stripped by caller) var parts=bstStr.split(':'); if(parts.length<2)return ''; var h=parseInt(parts[0],10); var m=parts[1]; // NJ/NY is EDT = UTC-4, BST = UTC+1, so ET = BST - 5 var eth=((h-5)+24)%24; var ampm=eth<12?'am':'pm'; var h12=eth%12||12; return h12+':'+m+ampm+' ET'; } function renderTodayBar(){ var bar=document.getElementById('today-bar'); var label=document.getElementById('today-bar-label'); var feed=document.getElementById('today-matches'); if(!bar||!feed)return; var now=new Date(); var days=['Sun','Mon','Tue','Wed','Thu','Fri','Sat']; var months=['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']; var todayStr=days[now.getDay()]+' '+now.getDate()+' '+months[now.getMonth()]; var myTeamCodes=[]; if(state.drawn){ Object.values(state.assignments).forEach(function(teams){ teams.forEach(function(tn){ var t=TEAMS.find(function(x){return x.name===tn}); if(t)myTeamCodes.push(t.code); }); }); } // Find today's matches involving drawn teams var todayMatches=SCHEDULE.filter(function(m){ return m.d===todayStr&&m.t.length===2&&myTeamCodes.length&&m.t.some(function(c){return myTeamCodes.indexOf(c)>=0}); }); // Find next 2 upcoming matches (any) if no matches today for my teams var nextMatches=[]; if(!todayMatches.length){ // walk schedule to find first 2 future group matches var found=0; for(var i=0;i=0; var mine2=myTeamCodes.indexOf(m.t[1])>=0; var f1=flagCache[m.t[0]]?'':(t1.emoji||m.t[0]); var f2=flagCache[m.t[1]]?'':(t2.emoji||m.t[1]); var bstClean=m.uk.replace('\u2020',''); var etStr=bstToET(bstClean); return '
' +f1+' '+m.t[0]+'' +' vs ' +f2+' '+m.t[1]+'' +' '+m.uk+' BST / '+etStr+' • '+m.v+'' +'
'; }).join(''); } else { // Show "no matches today, next up" if(label)label.innerHTML='📅 NEXT UPCOMING MATCHES'; bar.style.background='linear-gradient(135deg,rgba(42,57,141,.15),rgba(2,15,42,.3))'; bar.style.borderBottomColor='rgba(42,57,141,.4)'; feed.innerHTML=nextMatches.map(function(m){ var t1=TEAMS.find(function(x){return x.code===m.t[0]})||{emoji:'',code:m.t[0]}; var t2=TEAMS.find(function(x){return x.code===m.t[1]})||{emoji:'',code:m.t[1]}; var f1=flagCache[m.t[0]]?'':(t1.emoji||m.t[0]); var f2=flagCache[m.t[1]]?'':(t2.emoji||m.t[1]); var bstClean=m.uk.replace('\u2020',''); var etStr=bstToET(bstClean); return '
' +''+m.d+' ' +f1+' '+m.t[0]+'' +' vs ' +f2+' '+m.t[1]+'' +' '+m.uk+' BST / '+etStr+' • '+m.v+'' +'
'; }).join(''); } } /* -- TEAM MODAL -- */ function openTeamModal(teamName){ var t=TEAMS.find(function(x){return x.name===teamName}); if(!t)return; var modal=document.getElementById('team-modal'); var inner=document.getElementById('team-modal-content'); if(!modal||!inner)return; // Find next matches for this team var upcoming=SCHEDULE.filter(function(m){ return m.t.indexOf(t.code)>=0&&m.uk; }).slice(0,3); var stage=state.teamStages[teamName]||'tbd'; var stageInfo=STAGES[stage]||{label:'Not played yet',pts:0}; // Find who owns this team var owner=Object.entries(state.assignments).find(function(e){return e[1].indexOf(teamName)>=0}); var flagHtml=flagCache[t.code] ?'' :(t.emoji?''+t.emoji+'':''); var matchRows=upcoming.length ?upcoming.map(function(m){ var opp=m.t[0]===t.code?m.t[1]:m.t[0]; var oppT=TEAMS.find(function(x){return x.code===opp})||{emoji:'',code:opp}; var oppFlag=flagCache[opp]?'':(oppT.emoji||opp); return '
' +''+m.uk+' BST / '+bstToET(m.uk.replace("\u2020",""))+'' +''+m.d+'' +'vs '+oppFlag+' '+opp+'' +''+m.v+'' +'
'; }).join('') :'

No upcoming group fixtures

'; inner.innerHTML= '
' +flagHtml +'
' +'
'+t.name+'
' +'
FIFA Rank #'+t.rank+(t.rank<=10?' • ★ Top 10':t.rank<=20?' • Top 20':'')+'
' +(owner?'
Drawn by '+owner[0]+'
':'') +'
' +'
' +'
' +'Current stage' +''+stageInfo.label+'' +'
' +'
UPCOMING FIXTURES
' +matchRows; modal.style.display='flex'; } function closeTeamModal(){ var modal=document.getElementById('team-modal'); if(modal)modal.style.display='none'; } /* -- LIVE MATCH INDICATOR -- */ function getLiveTeams(){ var now=new Date(); var days=['Sun','Mon','Tue','Wed','Thu','Fri','Sat']; var months=['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']; var todayStr=days[now.getDay()]+' '+now.getDate()+' '+months[now.getMonth()]; var liveSet={}; SCHEDULE.forEach(function(m){ if(m.d!==todayStr||!m.uk||!m.t.length)return; var timeStr=m.uk.replace('\u2020',''); var parts=timeStr.split(':'); if(parts.length<2)return; var h=parseInt(parts[0],10),mi=parseInt(parts[1],10); var kickoff=new Date(now); kickoff.setUTCHours(h-1,mi,0,0); var diff=(now-kickoff)/60000; if(diff>=0&&diff<=105)m.t.forEach(function(c){liveSet[c]=true;}); }); return liveSet; } /* -- BANTER BOARD (Firebase realtime) -- */ var replyToId=null; var _fbApp=null; var _fbDb=null; var _fbRef=null; var _fbMessages=[]; function initFirebase(){ if(_fbApp)return; // Dynamically load Firebase SDKs then connect function loadScript(src,cb){ var s=document.createElement('script'); s.src=src; s.onload=cb; s.onerror=function(){ document.getElementById('banter-status').textContent='Offline (CDN blocked)'; document.getElementById('banter-status').style.color='var(--gray)'; }; document.head.appendChild(s); } var appUrl='https://www.gstatic.com/firebasejs/9.23.0/firebase-app-compat.js'; var dbUrl='https://www.gstatic.com/firebasejs/9.23.0/firebase-database-compat.js'; loadScript(appUrl,function(){ loadScript(dbUrl,function(){ try{ var firebaseConfig={ apiKey:'AIzaSyBU6vWqHUbHSnIPdjcGpC3BlwzlwhL24jg', authDomain:'wc2026-sweepstake-dbd56.firebaseapp.com', databaseURL:'https://wc2026-sweepstake-dbd56-default-rtdb.europe-west1.firebasedatabase.app', projectId:'wc2026-sweepstake-dbd56', storageBucket:'wc2026-sweepstake-dbd56.firebasestorage.app', messagingSenderId:'11571340466', appId:'1:11571340466:web:ebfbf6f935ce22ea98d5ab' }; _fbApp=firebase.initializeApp(firebaseConfig); _fbDb=firebase.database(); _fbRef=_fbDb.ref('banter'); _fbRef.on('value',function(snapshot){ var data=snapshot.val(); _fbMessages=[]; if(data){ Object.keys(data).forEach(function(k){_fbMessages.push(data[k]);}); _fbMessages.sort(function(a,b){return a.id-b.id;}); } renderBanter(); updateBanterDot(); }); document.getElementById('banter-status').textContent='Live'; document.getElementById('banter-status').style.color='var(--wc-green)'; }catch(e){ console.warn('Firebase init failed:',e); document.getElementById('banter-status').textContent='Offline'; document.getElementById('banter-status').style.color='var(--gray)'; } }); }); } function updateBanterDot(){ var lastSeen=parseInt(localStorage.getItem('banter-last-seen')||'0',10); var hasNew=_fbMessages.some(function(m){return m.id>lastSeen;}); var dot=document.getElementById('banter-dot'); if(dot)dot.style.display=hasNew?'inline-block':'none'; } function setReply(id){ var msg=_fbMessages.find(function(m){return m.id===id;}); if(!msg)return; replyToId=id; var preview=document.getElementById('banter-reply-preview'); var previewText=document.getElementById('banter-reply-text'); if(preview&&previewText){ previewText.innerHTML=''+msg.name+': '+msg.text.slice(0,60)+(msg.text.length>60?'...':''); preview.style.display='flex'; } var ta=document.getElementById('banter-msg'); if(ta)ta.focus(); } function clearReply(){ replyToId=null; var preview=document.getElementById('banter-reply-preview'); if(preview)preview.style.display='none'; } function renderBanter(){ var sel=document.getElementById('banter-name'); if(sel){ var cur=sel.value; sel.innerHTML=state.players.length ?state.players.map(function(p){return '';}).join('') :''; } var lastSeen=parseInt(localStorage.getItem('banter-last-seen')||'0',10); var msgs=_fbMessages; var feed=document.getElementById('banter-feed'); if(!feed)return; if(!msgs.length){ feed.innerHTML='
No messages yet. Start the banter! 🗣
'; return; } feed.innerHTML=msgs.slice().reverse().map(function(m,i){ var pi=state.players.indexOf(m.name); var col=pi>=0?pc(pi):{bg:'#444'}; var initials=m.name.split(' ').map(function(w){return w[0];}).join('').toUpperCase().slice(0,2); var ts=new Date(m.ts).toLocaleTimeString('en-GB',{hour:'2-digit',minute:'2-digit'}); var dateStr=new Date(m.ts).toLocaleDateString('en-GB',{day:'numeric',month:'short'}); var isNew=m.id>lastSeen; var replyHtml=''; if(m.replyTo){ var orig=_fbMessages.find(function(x){return x.id===m.replyTo;}); if(orig){ var origPi=state.players.indexOf(orig.name); var origCol=origPi>=0?pc(origPi):{bg:'#444'}; replyHtml='
' +''+orig.name+' ' +''+orig.text.slice(0,60)+(orig.text.length>60?'...':'')+'' +'
'; } } return '
' +'
'+initials+'
' +'
' +replyHtml +'
' +''+m.name+'' +(isNew?'':'') +''+dateStr+' '+ts+'' +'' +'' +'
' +'
'+m.text+'
' +'
' +'
'; }).join(''); } function scrollToBanter(id){ var el=document.getElementById('banter-msg-'+id); if(el){el.scrollIntoView({behavior:'smooth',block:'center'});el.style.background='rgba(240,180,41,.1)';setTimeout(function(){el.style.background='';},1200);} } function markBanterRead(){ if(!_fbMessages.length)return; var maxId=Math.max.apply(null,_fbMessages.map(function(m){return m.id;})); localStorage.setItem('banter-last-seen',maxId); var dot=document.getElementById('banter-dot'); if(dot)dot.style.display='none'; } function postBanter(){ var name=document.getElementById('banter-name').value; var msg=document.getElementById('banter-msg').value.trim(); if(!name||!msg)return; if(!_fbRef){alert('Not connected to Firebase yet. Please wait a moment and try again.');return;} var entry={id:Date.now(),name:name,text:msg,ts:new Date().toISOString()}; if(replyToId)entry.replyTo=replyToId; _fbRef.push(entry); document.getElementById('banter-msg').value=''; clearReply(); markBanterRead(); } function deleteBanter(id){ if(!_fbRef)return; // Find the Firebase key for this message _fbRef.once('value',function(snapshot){ snapshot.forEach(function(child){ if(child.val().id===id){ child.ref.remove(); } }); }); } /* -- BRACKET PREDICTOR -- */ /* Bracket structure: 32 teams -> R32 (16 matches) -> R16 (8) -> QF (4) -> SF (2) -> Final (1) state.bracket = { rounds: [ [matchObj,...], ... ] // 5 rounds: r32, r16, qf, sf, final } matchObj = { t: [teamNameOrNull, teamNameOrNull], winner: teamNameOrNull } */ var BRACKET_ROUND_NAMES=['Round of 32','Round of 16','Quarter-finals','Semi-finals','Final']; function initBracket(){ if(!state.drawn)return; // WC 2026 official R32 matchup slots by group position // Format: [slot description, group codes for team options] // Each match: {label, groups} where groups are the pool of teams to pick from // Based on official FIFA WC2026 bracket: 12 group winners + 12 runners-up + 8 best 3rds // We simplify: show all teams from the relevant groups as options, user taps to pick var R32_SLOTS=[ // Match 1-16 based on official WC2026 bracket structure // Group winners vs best 3rds / runners-up {a:['A'],b:['B']}, // 1A v 2B {a:['C'],b:['D']}, // 1C v 2D {a:['E'],b:['F']}, // 1E v 2F {a:['G'],b:['H']}, // 1G v 2H {a:['I'],b:['J']}, // 1I v 2J {a:['K'],b:['L']}, // 1K v 2L {a:['B'],b:['A']}, // 1B v 2A {a:['D'],b:['C']}, // 1D v 2C {a:['F'],b:['E']}, // 1F v 2E {a:['H'],b:['G']}, // 1H v 2G {a:['J'],b:['I']}, // 1J v 2I {a:['L'],b:['K']}, // 1L v 2K // Last 4 matches involve 3rd-place qualifiers - use cross-group pools {a:['A','B'],b:['C','D']}, {a:['E','F'],b:['G','H']}, {a:['I','J'],b:['K','L']}, {a:['A','C','E'],b:['B','D','F']} ]; // Build a lookup: group letter -> drawn teams in that group var groupMap={}; var SCHEDULE_GROUPS={ A:['MEX','RSA','KOR','CZE'],B:['CAN','BIH','QAT','SUI'], C:['BRA','MAR','HAI','SCO'],D:['USA','PAR','AUS','TUR'], E:['GER','CUW','CIV','ECU'],F:['NED','JPN','SWE','TUN'], G:['BEL','EGY','IRN','NZL'],H:['ESP','CPV','KSA','URU'], I:['FRA','SEN','IRQ','NOR'],J:['ARG','ALG','AUT','JOR'], K:['POR','COD','UZB','COL'],L:['ENG','CRO','GHA','PAN'] }; var drawnCodes={}; Object.values(state.assignments).forEach(function(ts){ ts.forEach(function(tn){ var t=TEAMS.find(function(x){return x.name===tn;}); if(t)drawnCodes[t.code]=tn; }); }); Object.keys(SCHEDULE_GROUPS).forEach(function(g){ groupMap[g]=SCHEDULE_GROUPS[g].filter(function(c){return drawnCodes[c];}).map(function(c){return drawnCodes[c];}); }); var matches=R32_SLOTS.map(function(slot){ // pool for side a: all drawn teams from those groups var poolA=[],poolB=[]; slot.a.forEach(function(g){poolA=poolA.concat(groupMap[g]||[]);}); slot.b.forEach(function(g){poolB=poolB.concat(groupMap[g]||[]);}); // pick first from each pool as default slot (user can change by tapping) return {t:[poolA[0]||null,poolB[0]||null],poolA:poolA,poolB:poolB,winner:null}; }); var rounds=[matches]; for(var r=0;r<4;r++){ var prev=rounds[r]; var next=[]; for(var j=0;j=4)return; var m=state.bracket.rounds[round][match]; if(!m)return; // if the old team (being replaced) was the winner, clear their downstream too var oldTeam=m.t[slot]; if(oldTeam&&m.winner===oldTeam){ m.winner=null; var nextMatch=Math.floor(match/2); var nextSlot=match%2; clearDownstream(round+1,nextMatch,oldTeam,nextSlot); if(state.bracket.rounds[round+1][nextMatch]){ state.bracket.rounds[round+1][nextMatch].t[nextSlot]=null; } } } function resetBracket(){ if(!confirm('Reset bracket prediction?'))return; state.bracket=null; save(); renderBracket(); } function renderBracket(){ var el=document.getElementById('bracket-content'); var champCard=document.getElementById('bracket-champion-card'); if(!el)return; if(!state.drawn){el.innerHTML='
Do the draw first to unlock the bracket predictor.
';if(champCard)champCard.style.display='none';return;} if(!state.bracket||!state.bracket.rounds||!state.bracket.rounds[0]||!state.bracket.rounds[0].length){ el.innerHTML='

Uses the 12 official WC 2026 groups

'; if(champCard)champCard.style.display='none'; return; } var rounds=state.bracket.rounds; var html='
'; for(var r=0;r'; html+='
'; for(var m=0;m=0;}); var flagHtml=flagCache[ct.code]?'':(ct.emoji?''+ct.emoji+'':''); document.getElementById('bracket-champion-display').innerHTML= '
' +'
\uD83C\uDFC6
' +'
'+flagHtml+'
' +'
'+champ+'
' +(owner?'
Drawn by '+owner[0]+'
':'') +'
'; } else if(champCard){ champCard.style.display='none'; } } function renderBracketMatch(round,matchIdx,m){ var t0=m.t[0]; var t1=m.t[1]; var w=m.winner; function teamHtml(tn,slot){ var pool=slot===0?(m.poolA||[]):(m.poolB||[]); if(!tn&&!pool.length){ return '
TBD
'; } // If round 0 and pool has multiple options, show a mini-select if(round===0&&pool.length>1){ var selOpts=pool.map(function(ptn){ var pt=TEAMS.find(function(x){return x.name===ptn;})||{code:'???'}; return ''; }).join(''); var curT=tn?TEAMS.find(function(x){return x.name===tn;})||{code:'???',emoji:'',rank:99}:{code:'?',emoji:'',rank:99}; var flagHtml=tn&&flagCache[curT.code]?'': (tn&&curT.emoji?''+curT.emoji+'':''); return '
' +flagHtml +'' +(w===tn?'\u2714':'') +(tn?'':'') +'
'; } if(!tn){ return '
TBD
'; } var t=TEAMS.find(function(x){return x.name===tn;})||{code:'???',emoji:'',rank:99}; var isW=w===tn; var isL=w&&w!==tn; var flagHtml2=flagCache[t.code]?'':(t.emoji?''+t.emoji+'':''); var owner=Object.entries(state.assignments).find(function(e){return e[1].indexOf(tn)>=0;}); var ownerInitials=owner?owner[0].split(' ').map(function(w2){return w2[0];}).join('').toUpperCase().slice(0,2):''; var pi=owner?state.players.indexOf(owner[0]):-1; var ownerCol=pi>=0?pc(pi).bg:'#666'; return '
' +flagHtml2 +''+t.code+'' +(ownerInitials?''+ownerInitials+'':'') +(isW?'\u2714':'') +'
'; } return '
'+teamHtml(t0,0)+teamHtml(t1,1)+'
'; } function swapBracketSlot(round,match,slot,teamName){ if(!state.bracket)return; var m=state.bracket.rounds[round][match]; if(!m)return; m.t[slot]=teamName; if(m.winner&&m.winner!==m.t[0]&&m.winner!==m.t[1])m.winner=null; save();renderBracket(); } function shareBracket(){ if(!state.bracket)return; var rounds=state.bracket.rounds; var rnames=['R32','R16','QF','SF','Final']; var txt='\u26BD WC 2026 BRACKET PREDICTION \u26BD\n'; for(var r=0;rfetchResults()); } else { setSyncStatus('','No API key set \u2014 add one in Setup for live results'); }